# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Gitlab::BackgroundMigration::FixVulnerabilityReadsHasIssues, schema: 20230302185739, feature_category: :vulnerability_management do # rubocop:disable Layout/LineLength
  let(:namespaces) { table(:namespaces) }
  let(:projects) { table(:projects) }
  let(:users) { table(:users) }
  let(:scanners) { table(:vulnerability_scanners) }
  let(:vulnerabilities) { table(:vulnerabilities) }
  let(:vulnerability_reads) { table(:vulnerability_reads) }
  let(:work_item_types) { table(:work_item_types) }
  let(:issues) { table(:issues) }
  let(:vulnerability_issue_links) { table(:vulnerability_issue_links) }

  let(:namespace) { namespaces.create!(name: 'user', path: 'user') }
  let(:project) { projects.create!(namespace_id: namespace.id, project_namespace_id: namespace.id) }
  let(:user) { users.create!(username: 'john_doe', email: 'johndoe@gitlab.com', projects_limit: 10) }
  let(:scanner) { scanners.create!(project_id: project.id, external_id: 'external_id', name: 'Test Scanner') }
  let(:work_item_type) { work_item_types.create!(name: 'test') }

  let(:vulnerability_records) do
    Array.new(4).map do |_, n|
      vulnerabilities.create!(
        project_id: project.id,
        author_id: user.id,
        title: "vulnerability #{n}",
        severity: 1,
        confidence: 1,
        report_type: 1
      )
    end
  end

  let(:vulnerabilities_with_issues) { [vulnerability_records.first, vulnerability_records.third] }
  let(:vulnerabilities_without_issues) { vulnerability_records - vulnerabilities_with_issues }

  let(:vulnerability_read_records) do
    vulnerability_records.map do |vulnerability|
      vulnerability_reads.create!(
        project_id: project.id,
        vulnerability_id: vulnerability.id,
        scanner_id: scanner.id,
        has_issues: false,
        severity: 1,
        report_type: 1,
        state: 1,
        uuid: SecureRandom.uuid
      )
    end
  end

  let!(:issue_links) do
    vulnerabilities_with_issues.map do |vulnerability|
      issue = issues.create!(
        title: vulnerability.title,
        author_id: user.id,
        project_id: project.id,
        confidential: true,
        work_item_type_id: work_item_type.id,
        namespace_id: namespace.id
      )

      vulnerability_issue_links.create!(
        vulnerability_id: vulnerability.id,
        issue_id: issue.id
      )
    end
  end

  def vulnerability_read_for(vulnerability)
    vulnerability_read_records.find { |read| read.vulnerability_id == vulnerability.id }
  end

  subject(:perform_migration) do
    described_class.new(
      start_id: issue_links.first.vulnerability_id,
      end_id: issue_links.last.vulnerability_id,
      batch_table: :vulnerability_issue_links,
      batch_column: :vulnerability_id,
      sub_batch_size: issue_links.size,
      pause_ms: 0,
      connection: ActiveRecord::Base.connection
    ).perform
  end

  it 'only changes records with issue links' do
    expect(vulnerability_read_records).to all(have_attributes(has_issues: false))

    perform_migration

    vulnerabilities_with_issues.each do |vulnerability|
      expect(vulnerability_read_for(vulnerability).reload.has_issues).to eq(true)
    end

    vulnerabilities_without_issues.each do |vulnerability|
      expect(vulnerability_read_for(vulnerability).reload.has_issues).to eq(false)
    end
  end
end
